import gobject
import Sysaccess
import Exceptions

class Shares(gobject.GObject):
    '''this class is the container for share objects'''
    
    __gsignals__ = {
        # set signal is emit when a share is set
        # callback has to look like : def callback(shares, share)
        'set' : (gobject.SIGNAL_DETAILED, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
        # add signal is emit when a share is add
        # callback has to look like : def callback(shares, share)
        'add' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
        # remove signal is emit when a location is remove
        # callback has to look like : def callback(shares, location,share_id) <-- id because this share does not exist anymore
        'remove' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,gobject.TYPE_PYOBJECT)),
    }
    
    def __init__(self,controller):
        '''constructor'''
        
        gobject.GObject.__init__(self)
        self.controller = controller        # a reference to the main controller
        self.id = None                      # unique identifier for shares objects
        self.store = None                   # real container for location objects
        self.lock = False
        self.connect('set',self.save)       #\
        self.connect('add',self.save)       #-auto save
        self.connect('remove',self.save)    #/
        self.attrib_to_load = ["name","protocol","server","path","mount_point","domain","login","password","options","port","automount"]
        
    def load(self):
        '''initialize store and id with the saved pickle or default'''
        
        load = Sysaccess.load(self.controller.config.path['SHARE PICKLE'])
        if load:
            self.id = load[0]
            self.store = {}
            for share_id,share in load[1].iteritems():
                new_share = Share(share_id)
                new_share.location = self.controller.locations[share.location.id]
                for attrib in self.attrib_to_load:
                    new_share.__dict__[attrib] = share.__dict__[attrib]
                self.store[share_id] = new_share
        else:
            raise Exceptions.PickleLoadException(self.controller.config.path['SHARE PICKLE'])
    
    def load_defaults(self):
        self.id = 0
        self.store = {}
        self.save()
    
    def save(self,*args):
        '''save store and id'''
        
        Sysaccess.save([self.id,self.store],self.controller.config.path['SHARE PICKLE']) # use a List an not a 2-tuple beccause of the space empty dict  in tuple Pickle Bug
    
    def get_id(self):
        '''generate an unique id to pass to Location constructor'''
        self.id += 1
        return self.id
    
    def get_share_by_addr(self,server,path):
        server = server.lower()
        path = path.lower().strip('/')
        for share in self.store.itervalues():
            if share.server.lower() == server and share.path.lower().strip('/') == path:
                return share
    
    def get_shares_by_location(self,location):
        '''return all the shares attached to the gived location'''  
        result = []
        for share in self.store.itervalues():
            if share.location == location:
                result.append(share)
        return result
    
    def set_mounted(self,share,value):
        if share.mounted != value:
            if value:
                share.mounted = value
                self.emit('set::mount',share)
            else:
                share.mounted = value
                self.emit('set::unmount',share)
                
    def set_latency(self,share,value):
        if share.latency != value:
            share.latency = value
            self.emit('set::latency',share)
    
    def set_automount(self,share,value):
        if share.automount != value:
            share.lock_automount = False;
            share.automount = value
            self.emit('set::automount',share)
            
    def __getitem__(self,item_id):
        '''getter'''    
        if self.lock:
            self.__wait__()
        return self.store[item_id]
    
    def __setitem__(self,item_id,share):
        '''setter witch emit add/set signal'''
        if self.lock:
            self.__wait__()
        if item_id in self.store:
            mounted = self.store[item_id].mounted
            if mounted:
                self.controller.unmount_share(self.store[item_id])
            self.store[item_id] = share
            self.emit('set',self.store[item_id])
            if mounted:
                self.controller.mount_share(self.store[item_id])    
        else :
            self.store[item_id] = share
            self.emit('add',self.store[item_id])
    
    def __delitem__(self,item_id):
        '''try to remove a location'''
        if self.lock:
            self.__wait__()
        location = self.store[item_id].location
        del self.store[item_id]
        self.emit('remove',location,item_id)
    
    def __wait__(self):
        while self.lock:
            print 'wait'
        
    def __iter__(self):
        '''iterator shortcut'''
        self.lock = True
        tmp = self.store.iteritems()
        self.lock = False
        return tmp

    def __repr__(self):
        '''repr override'''
        
        return self.store.__repr__()

class Share():
    '''represent a share with all parameters needed to mount/manage it'''
    
    def __init__(self,id):
        """constructor"""
        
        self.id = id
        self.protocol = None
        self.name = ""
        self.location = None    # reference to the share location
        
        self.server = ""
        self.mount_point = ""
        self.path = ""
        self.domain = ""
        self.login = ""
        self.password = ""
        self.options = {}
        self.port = None
        self.automount = False
        
        self.lock_automount = False
        self.latency = None
        self.mounted = False
        self.remount = False
        self.locked = False
    
    def __repr__(self):
        '''repr override'''
        return "%s (%s)" % (self.name,self.id)
    
    def build_option(self):
        """
        Output : return the string option
        Dev : MG
        """
        option_string = ""
        if self.protocol == "SAMBA": 
            if not len(self.options["domain"]) :
                self.options["domain"] = "workgroup"
            for key in self.options:
                   if len(self.options[key]):
                    option_string += key+"="+self.options[key]+","
            if len(option_string):
                option_string = "-o "+option_string[0:len(option_string)-1]
            return option_string
    
    
    def build_mount_cmd(self):
        if self.protocol == 'SAMBA':
            self.options = {"domain":self.domain,"user":self.login,"password":self.password}
            cmd = ['mount.cifs','//'+self.server+'/'+self.path,self.mount_point,self.build_option()]
        if self.protocol == 'SSH':
            cmd = ['sshfs', self.login + '@' + self.server + ':' + self.path,self.mount_point,'-oallow_other','-opassword_stdin']
        return cmd
    
#    def build_option(self,options):
#        """
#        Output : return the string option
#        Dev : Bewiwi
#        """
#        option_string = ""
#        for option in options:
#            if options[option]!= None and options[option]!= "":
#                option_string += option+"="+options[option]+","
#            elif self.protocol == 'SAMBA' and option == "password":
#                option_string += option+"="+options[option]+"," 
#        if len(option_string) != 0:
#            option_string = "-o "+option_string
#        return option_string[0:len(option_string)-1]
#    
#    
#    def build_mount_cmd(self):
#        if self.protocol == 'SAMBA':
#            self.options = {"domain":self.domain,"user":self.login,"password":self.password}
#            cmd = ['mount.cifs','//'+self.server+'/'+self.path,self.mount_point,self.build_option(self.options)]
#        if self.protocol == 'SSH':
#            cmd = ['sshfs', self.login + '@' + self.server + ':' + self.path,self.mount_point,'-oallow_other','-opassword_stdin']
#        return cmd